home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / hurd / hurdsig.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  23KB  |  765 lines

  1. /* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <gnu-stabs.h>
  22. #include <hurd.h>
  23. #include <hurd/signal.h>
  24. #include <cthreads.h>        /* For `struct mutex'.  */
  25. #include <string.h>
  26. #include "hurdmalloc.h"        /* XXX */
  27.  
  28. struct mutex _hurd_siglock = MUTEX_INITIALIZER;
  29. int _hurd_stopped;
  30.  
  31. /* Port that receives signals and other miscellaneous messages.  */
  32. mach_port_t _hurd_msgport;
  33.  
  34. /* Thread listening on it.  */
  35. thread_t _hurd_msgport_thread;
  36.  
  37. /* Thread which receives task-global signals.  */
  38. thread_t _hurd_sigthread;
  39.  
  40. /* Linked-list of per-thread signal state.  */
  41. struct hurd_sigstate *_hurd_sigstates;
  42.  
  43. struct hurd_sigstate *
  44. _hurd_thread_sigstate (thread_t thread)
  45. {
  46.   struct hurd_sigstate *ss;
  47.   __mutex_lock (&_hurd_siglock);
  48.   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
  49.     if (ss->thread == thread)
  50.       break;
  51.   if (ss == NULL)
  52.     {
  53.       ss = malloc (sizeof (*ss));
  54.       if (ss == NULL)
  55.     __libc_fatal ("hurd: Can't allocate thread sigstate\n");
  56.       memset (ss, 0, sizeof (*ss));
  57.       ss->thread = thread;
  58.       __mutex_init (&ss->lock);
  59.       ss->next = _hurd_sigstates;
  60.       _hurd_sigstates = ss;
  61.     }
  62.   __mutex_lock (&ss->lock);
  63.   __mutex_unlock (&_hurd_siglock);
  64.   return ss;
  65. }
  66.  
  67. #include <hurd/fd.h>
  68. #include <hurd/core.h>
  69. #include <hurd/paths.h>
  70. #include <setjmp.h>
  71. #include <fcntl.h>
  72. #include <sys/wait.h>
  73. #include "thread_state.h"
  74. #include <hurd/msg_server.h>
  75. #include <hurd/msg_reply.h>    /* For __sig_post_reply.  */
  76.  
  77. jmp_buf _hurd_sigthread_fault_env;
  78.  
  79. int _hurd_core_limit;    /* XXX */
  80.  
  81. /* Call the core server to mummify us before we die.
  82.    Returns nonzero if a core file was written.  */
  83. static int
  84. write_corefile (int signo, int sigcode)
  85. {
  86.   error_t err;
  87.   volatile mach_port_t coreserver;
  88.   volatile file_t file;
  89.   char *volatile name;
  90.   char *volatile target;
  91.  
  92.   /* XXX RLIMIT_CORE */
  93.  
  94.   coreserver = MACH_PORT_NULL;
  95.   if (!setjmp (_hurd_sigthread_fault_env))
  96.     {
  97.       name = getenv ("CORESERVER");
  98.       if (name != NULL)
  99.     coreserver = __path_lookup (name, 0, 0);
  100.     }
  101.  
  102.   if (coreserver == MACH_PORT_NULL)
  103.     coreserver = __path_lookup (_SERVERS_CORE, 0, 0);
  104.   if (coreserver == MACH_PORT_NULL)
  105.     return 0;
  106.  
  107.   file = MACH_PORT_NULL;
  108.   name = NULL;
  109.   if (!setjmp (_hurd_sigthread_fault_env))
  110.     {
  111.       name = getenv ("COREFILE");
  112.       if (name != NULL)
  113.     file = __path_lookup (name, O_WRONLY|O_CREAT, 0666 & ~_hurd_umask);
  114.     }
  115.   if (name == NULL || file == MACH_PORT_NULL)
  116.     {
  117.       name = (char *) "core";
  118.       file = __path_lookup (name, O_WRONLY|O_CREAT, 0666 & ~_hurd_umask);
  119.     }
  120.  
  121.   if (file == MACH_PORT_NULL)
  122.     return 0;
  123.  
  124.   if (setjmp (_hurd_sigthread_fault_env))
  125.     /* We bombed in getenv.  */
  126.     target = NULL;
  127.   else
  128.     {
  129.       target = getenv ("GNUTARGET");
  130.       /* Fault now if TARGET is a bogus string.  */
  131.       (void) strlen (target);
  132.     }
  133.  
  134.   err = __core_dump_task (coreserver,
  135.               __mach_task_self (),
  136.               file,
  137.               signo, sigcode,
  138.               target);
  139.   __mach_port_deallocate (__mach_task_self (), coreserver);
  140.   __mach_port_deallocate (__mach_task_self (), file);
  141.   if (err)
  142.     (void) remove (name);
  143.   return !err;
  144. }
  145.  
  146.  
  147. /* How long to give servers to respond to
  148.    interrupt_operation before giving up on them.  */
  149. mach_msg_timeout_t _hurd_interrupt_timeout = 1000; /* One second.  */
  150.  
  151. /* SS->thread is suspended.  Fills STATE in with its registers.
  152.    SS->lock is held and kept.  */
  153. static inline void
  154. abort_rpcs (struct hurd_sigstate *ss, int signo, void *state)
  155. {
  156.   unsigned int count = MACHINE_THREAD_STATE_COUNT;
  157.   __thread_abort (ss->thread);
  158.   if (__thread_get_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
  159.               state, &count) != KERN_SUCCESS ||
  160.       count != MACHINE_THREAD_STATE_COUNT)
  161.     /* What kind of thread?? */
  162.     return;            /* XXX */
  163.  
  164.   if (ss->intr_port != MACH_PORT_NULL)
  165.     {
  166.       /* Abort whatever the thread is doing.
  167.      If it is in the mach_msg syscall doing the send,
  168.      the syscall will return MACH_SEND_INTERRUPTED.  */
  169.       mach_port_t msging_port;
  170.       if (_hurd_thread_state_msging_p (state, &msging_port))
  171.     {
  172.       /* The thread was waiting for the RPC to return.
  173.          Abort the operation.  The RPC will return EINTR.  */
  174.  
  175.       struct
  176.         {
  177.           mach_msg_header_t header;
  178.           mach_msg_type_t type;
  179.           kern_return_t retcode;
  180.         } msg;
  181.       kern_return_t err;
  182.  
  183.       msg.header.msgh_remote_port = ss->intr_port;
  184.       msg.header.msgh_local_port = __mach_reply_port ();
  185.       msg.header.msgh_seqno = 0;
  186.       msg.header.msgh_id = 33000; /* interrupt_operation XXX */
  187.       err = __mach_msg (&msg.header,
  188.                 MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_TIMEOUT,
  189.                 sizeof (msg.header), sizeof (msg),
  190.                 msg.header.msgh_local_port,
  191.                 _hurd_interrupt_timeout,
  192.                 MACH_PORT_NULL);
  193.       if (err != MACH_MSG_SUCCESS)
  194.         /* The interrupt didn't work.
  195.            Destroy the receive right the thread is blocked on.  */
  196.         __mach_port_destroy (__mach_task_self (), msging_port);
  197.       else
  198.         /* In case the server returned something screwy.  */
  199.         __mach_msg_destroy (&msg.header);
  200.  
  201.       /* Tell the thread whether it should restart the
  202.          operation or return EINTR when it wakes up.  */
  203.       ss->intr_restart = ss->actions[signo].sa_flags & SA_RESTART;
  204.     }
  205.  
  206.       /* If the thread is anywhere before the system call trap,
  207.      it will start the operation after the signal is handled.
  208.      
  209.      If the thread is after the system call trap, but before it has
  210.      cleared SS->intr_port, the operation is already finished.  */
  211.     }
  212. }
  213.  
  214. /* Abort the RPCs being run by all threads but this one;
  215.    all other threads should be suspended.  */
  216. static inline void
  217. abort_all_rpcs (int signo, void *state)
  218. {
  219.   thread_t me = __mach_thread_self ();
  220.   thread_t *threads;
  221.   mach_msg_type_number_t nthreads, i;
  222.  
  223.   __task_threads (__mach_task_self (), &threads, &nthreads);
  224.   for (i = 0; i < nthreads; ++i)
  225.     {
  226.       if (threads[i] != me)
  227.     {
  228.       struct hurd_sigstate *ss = _hurd_thread_sigstate (threads[i]);
  229.       abort_rpcs (ss, signo, state);
  230.       __mutex_unlock (&ss->lock);
  231.     }
  232.       __mach_port_deallocate (__mach_task_self (), threads[i]);
  233.     }
  234. }
  235.  
  236.  
  237. struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
  238. struct mutex _hurd_signal_preempt_lock;
  239.  
  240.  
  241. /* Fetch the MiG reply port in use by the thread whose interrupted state is
  242.    described by *THREAD_STATE, and ensure that the thread will not try to
  243.    use it again.  */
  244.  
  245. static mach_port_t
  246. interrupted_reply_port (struct machine_thread_state *thread_state)
  247. {
  248.   mach_port_t port, *portloc;
  249.  
  250.   if (setjmp (_hurd_sigthread_fault_env))
  251.     /* Faulted trying to read the stack.  */
  252.     return MACH_PORT_NULL;
  253.  
  254.   portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
  255.     (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->SP);
  256.  
  257.   port = *portloc;
  258.   *portloc = MACH_PORT_NULL;
  259.   return port;
  260. }
  261.  
  262.  
  263. /* Deliver a signal.
  264.    SS->lock is held on entry and released before return.  */
  265. void
  266. _hurd_internal_post_signal (struct hurd_sigstate *ss,
  267.                 int signo, int sigcode,
  268.                 mach_port_t reply_port,
  269.                 mach_msg_type_name_t reply_port_type)
  270. {
  271.   struct machine_thread_state thread_state;
  272.   enum { stop, ignore, core, term, handle } act;
  273.   sighandler_t handler;
  274.   struct hurd_signal_preempt *pe;
  275.   sighandler_t (*preempt) (thread_t, int, int) = NULL;
  276.  
  277.   /* Check SS for pending signals and post them.  SS->lock is held on entry.
  278.      Return zero if no signals were pending.  If pending signals were posted,
  279.      unlock SS->lock and return nonzero.  */
  280.   inline int check_pending (struct hurd_sigstate *ss)
  281.     {
  282.       int signo;
  283.  
  284.       if (ss->pending)
  285.     for (signo = 1; signo < NSIG; ++signo)
  286.       if (__sigismember (&ss->pending, signo))
  287.         {
  288.           __sigdelset (&ss->pending, signo);
  289.           _hurd_internal_post_signal (ss, signo, ss->sigcodes[signo],
  290.                       reply_port, reply_port_type);
  291.           /* _hurd_internal_post_signal called us on SS before
  292.          returning, so no need to keep looping.  */
  293.           return 1;
  294.         }
  295.  
  296.       return 0;
  297.     }
  298.  
  299.   /* Check for a preempted signal.  */
  300.   __mutex_lock (&_hurd_signal_preempt_lock);
  301.   for (pe = _hurd_signal_preempt[signo]; pe != NULL; pe = pe->next)
  302.     if (sigcode >= pe->first && sigcode <= pe->last)
  303.       {
  304.     preempt = pe->handler;
  305.     break;
  306.       }
  307.   __mutex_unlock (&_hurd_signal_preempt_lock);
  308.  
  309.   handler = SIG_DFL;
  310.   if (preempt)
  311.     /* Let the preempting handler examine the thread.
  312.        If it returns SIG_DFL, we run the normal handler;
  313.        otherwise we use the handler it returns.  */
  314.     handler = (*preempt) (ss->thread, signo, sigcode);
  315.   if (handler == SIG_DFL)
  316.     handler = ss->actions[signo].sa_handler;
  317.  
  318.   if (handler == SIG_DFL)
  319.     /* Figure out the default action for this signal.  */
  320.     switch (signo)
  321.       {
  322.       case 0:
  323.     /* A sig_post msg with SIGNO==0 is sent to
  324.        tell us to check for pending signals.  */
  325.     act = ignore;
  326.     break;
  327.  
  328.       case SIGTTIN:
  329.       case SIGTTOU:
  330.       case SIGSTOP:
  331.       case SIGTSTP:
  332.     ss->pending &= ~sigmask (SIGCONT);
  333.     act = stop;
  334.     break;
  335.  
  336.       case SIGCONT:
  337.     ss->pending &= ~(sigmask (SIGSTOP) | sigmask (SIGTSTP) |
  338.              sigmask (SIGTTIN) | sigmask (SIGTTOU));
  339.     /* Fall through.  */
  340.       case SIGIO:
  341.       case SIGURG:
  342.       case SIGCHLD:
  343.       case SIGWINCH:
  344.     act = ignore;
  345.     break;
  346.  
  347.       case SIGQUIT:
  348.       case SIGILL:
  349.       case SIGTRAP:
  350.       case SIGIOT:
  351.       case SIGEMT:
  352.       case SIGFPE:
  353.       case SIGBUS:
  354.       case SIGSEGV:
  355.       case SIGSYS:
  356.     act = core;
  357.     break;
  358.  
  359.       case SIGINFO:
  360.     if (_hurd_pgrp == _hurd_pid)
  361.       {
  362.         /* We are the process group leader.  Since there is no
  363.            user-specified handler for SIGINFO, we use a default one
  364.            which prints something interesting.  We use the normal
  365.            handler mechanism instead of just doing it here to avoid the
  366.            signal thread faulting or blocking in this potentially hairy
  367.            operation.  */
  368.         act = handle;
  369.         handler = _hurd_siginfo_handler;
  370.       }
  371.     else
  372.       act = ignore;
  373.     break;
  374.  
  375.       default:
  376.     act = term;
  377.     break;
  378.       }
  379.   else if (handler == SIG_IGN)
  380.     act = ignore;
  381.   else
  382.     act = handle;
  383.  
  384.   if (_hurd_orphaned && act == stop &&
  385.       (signo & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
  386.         __sigmask (SIGTSTP))))
  387.     {
  388.       /* If we would ordinarily stop for a job control signal, but we are
  389.      orphaned so noone would ever notice and continue us again, we just
  390.      quietly die, alone and in the dark.  */
  391.       sigcode = signo;
  392.       signo = SIGKILL;
  393.       act = term;
  394.     }
  395.  
  396.   /* Handle receipt of a blocked signal.  */
  397.   if ((__sigismember (&ss->blocked, signo) && act != ignore) ||
  398.       (signo != SIGKILL && _hurd_stopped))
  399.     {
  400.       __sigaddset (&ss->pending, signo);
  401.       /* Save the code to be given to the handler when SIGNO is unblocked.  */
  402.       ss->sigcodes[signo] = sigcode;
  403.       act = ignore;
  404.     }
  405.  
  406.   /* Perform the chosen action for the signal.  */
  407.   switch (act)
  408.     {
  409.     case stop:
  410.       /* Stop all other threads and mark ourselves stopped.  */
  411.       __USEPORT (PROC,
  412.          ({
  413.            /* Hold the siglock while stopping other threads to be
  414.               sure it is not held by another thread afterwards.  */
  415.            __mutex_unlock (&ss->lock);
  416.            __mutex_lock (&_hurd_siglock);
  417.            __proc_dostop (port, __mach_thread_self ());
  418.            __mutex_unlock (&_hurd_siglock);
  419.            abort_all_rpcs (signo, &thread_state);
  420.            __proc_mark_stop (port, signo);
  421.          }));
  422.       _hurd_stopped = 1;
  423.  
  424.       __mutex_lock (&ss->lock);
  425.       if (ss->suspended)
  426.     {
  427.       /* There is a sigsuspend waiting.  Tell it to wake up.  */
  428.       ss->suspended = 0;
  429. #ifdef noteven
  430.       __condition_signal (&ss->arrived);
  431. #else
  432.       __mutex_unlock (&ss->lock);
  433. #endif
  434.     }
  435.       else
  436.     __mutex_unlock (&ss->lock);
  437.  
  438.       break;
  439.  
  440.     case ignore:
  441.       /* Nobody cares about this signal.  */
  442.       break;
  443.  
  444.     case term:            /* Time to die.  */
  445.     case core:            /* And leave a rotting corpse.  */
  446.       /* Have the proc server stop all other threads in our task.  */
  447.       __USEPORT (PROC, __proc_dostop (port, __mach_thread_self ()));
  448.       /* Abort all server operations now in progress.  */
  449.       abort_all_rpcs (signo, &thread_state);
  450.       /* The signal can now be considered delivered.
  451.      Don't make the killer wait for us to dump core.  */
  452.       if (reply_port)
  453.     __sig_post_reply (reply_port, reply_port_type, 0);
  454.       /* Tell proc how we died and then stick the saber in the gut.  */
  455.       _hurd_exit (W_EXITCODE (0, signo) |
  456.           /* Do a core dump if desired.  Only set the wait status
  457.                      bit saying we in fact dumped core if the operation was
  458.                      actually succesful.  */
  459.           (act == core && write_corefile (signo, sigcode) ?
  460.            WCOREFLAG : 0));
  461.       /* NOTREACHED */
  462.  
  463.     case handle:
  464.       /* Call a handler for this signal.  */
  465.       {
  466.     struct sigcontext *scp;
  467.  
  468.     /* Stop the thread and abort its pending RPC operations.  */
  469.     __thread_suspend (ss->thread);
  470.     abort_rpcs (ss, signo, &thread_state);
  471.  
  472.     /* Call the machine-dependent function to set the thread up
  473.        to run the signal handler, and preserve its old context.  */
  474.     scp = _hurd_setup_sighandler (ss->actions[signo].sa_flags,
  475.                       handler,
  476.                       &ss->sigaltstack,
  477.                       signo, sigcode,
  478.                       &thread_state);
  479.  
  480.     /* Set the machine-independent parts of the signal context.  */
  481.     scp->sc_mask = ss->blocked;
  482.     scp->sc_intr_port = ss->intr_port;
  483.     /* Fetch the thread variable for the MiG reply port,
  484.        and set it to MACH_PORT_NULL.  */
  485.     scp->sc_reply_port = interrupted_reply_port (&thread_state);
  486.  
  487.     /* Block SIGNO and requested signals while running the handler.  */
  488.     ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
  489.  
  490.     /* Start the thread running the handler.  */
  491.     __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
  492.                 (int *) &thread_state, MACHINE_THREAD_STATE_COUNT);
  493.     __thread_resume (ss->thread);
  494.     break;
  495.       }
  496.     }
  497.  
  498.   /* The signal has either been ignored or is now being handled.  We can
  499.      consider it delivered and reply to the killer.  The exception is
  500.      signal 0, which can be sent by a user thread to make us check for
  501.      pending signals.  In that case we want to deliver the pending signals
  502.      before replying.  */
  503.   if (signo != 0 && reply_port)
  504.     {
  505.       __sig_post_reply (reply_port, reply_port_type, 0);
  506.       reply_port = MACH_PORT_NULL;
  507.     }
  508.  
  509.   /* We get here only if we are handling or ignoring the signal;
  510.      otherwise we are stopped or dead by now.  We still hold SS->lock.
  511.      Check for pending signals, and loop to post them.  */
  512.   if (! check_pending (ss))
  513.     {
  514.       /* No more signals pending; SS->lock is still locked.  */
  515.       if (ss->suspended)
  516.     {
  517.       /* There is a sigsuspend waiting.  Tell it to wake up.  */
  518.       ss->suspended = 0;
  519. #ifdef noteven
  520.       __condition_signal (&ss->arrived);
  521. #else
  522.       __mutex_unlock (&ss->lock);
  523. #endif
  524.     }
  525.       else
  526.     __mutex_unlock (&ss->lock);
  527.     }
  528.  
  529.   /* No pending signals left undelivered for this thread.
  530.      If we were sent signal 0, we need to check for pending
  531.      signals for all threads.  */
  532.   if (signo == 0)
  533.     {
  534.       __mutex_lock (&_hurd_siglock);
  535.       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
  536.     {
  537.       __mutex_lock (&ss->lock);
  538.       if (! check_pending (ss))
  539.         __mutex_unlock (&ss->lock);
  540.     }
  541.       __mutex_unlock (&_hurd_siglock);
  542.     }
  543.  
  544.   /* All pending signals delivered to all threads.
  545.      Now we can send the reply message even for signal 0.  */
  546.   if (reply_port)
  547.     __sig_post_reply (reply_port, reply_port_type, 0);
  548. }
  549.  
  550. /* Implement the sig_post RPC from <hurd/msg.defs>;
  551.    sent when someone wants us to get a signal.  */
  552. kern_return_t
  553. _S_sig_post (mach_port_t me,
  554.          mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
  555.          int signo,
  556.          mach_port_t refport)
  557. {
  558.   struct hurd_sigstate *ss;
  559.  
  560.   if (signo < 0 || signo >= NSIG)
  561.     return EINVAL;
  562.  
  563.   if (refport == __mach_task_self ())
  564.     /* Can send any signal.  */
  565.     goto win;
  566.  
  567.   /* Avoid needing to check for this below.  */
  568.   if (refport == MACH_PORT_NULL)
  569.     return EPERM;
  570.  
  571.   switch (signo)
  572.     {
  573.     case SIGINT:
  574.     case SIGQUIT:
  575.     case SIGTSTP:
  576.     case SIGHUP:
  577.     case SIGINFO:
  578.       /* Job control signals can be sent by the controlling terminal.  */
  579.       if (__USEPORT (CTTYID, port == refport))
  580.     goto win;
  581.       break;
  582.  
  583.     case SIGCONT:
  584.       {
  585.     /* A continue signal can be sent by anyone in the session.  */
  586.     mach_port_t sessport;
  587.     if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
  588.       { 
  589.         int win = refport == sessport;
  590.         __mach_port_deallocate (__mach_task_self (), sessport);
  591.         if (win)
  592.           goto win;
  593.       }
  594.       }
  595.       break;
  596.  
  597.     case SIGIO:
  598.     case SIGURG:
  599.       {
  600.     /* Any io object a file descriptor refers to might send us
  601.        one of these signals using its async ID port for REFPORT.
  602.  
  603.        This is pretty wide open; it is not unlikely that some random
  604.        process can at least open for reading something we have open,
  605.        get its async ID port, and send us a spurious SIGIO or SIGURG
  606.        signal.  But BSD is actually wider open than that!--you can set
  607.        the owner of an io object to any process or process group
  608.        whatsoever and send them gratuitous signals.
  609.  
  610.        Someday we could implement some reasonable scheme for
  611.        authorizing SIGIO and SIGURG signals properly.  */
  612.  
  613.     int d;
  614.     __mutex_lock (&_hurd_dtable_lock);
  615.     for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
  616.       {
  617.         struct hurd_userlink ulink;
  618.         io_t port;
  619.         mach_port_t asyncid;
  620.         if (_hurd_dtable[d] == NULL)
  621.           continue;
  622.         port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
  623.         if (! __io_get_icky_async_id (port, &asyncid))
  624.           {
  625.         if (refport == asyncid)
  626.           /* Break out of the loop on the next iteration.  */
  627.           d = -1;
  628.         __mach_port_deallocate (__mach_task_self (), asyncid);
  629.           }
  630.         _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
  631.       }
  632.     /* If we found a lucky winner, we've set D to -1 in the loop.  */
  633.     if (d < 0)
  634.       goto win;
  635.       }
  636.     }
  637.  
  638.   /* If this signal is legit, we have done `goto win' by now.
  639.      When we return the error, mig deallocates REFPORT.  */
  640.   return EPERM;
  641.  
  642.  win:
  643.   /* Deallocate the REFPORT send right; we are done with it.  */
  644.   __mach_port_deallocate (__mach_task_self (), refport);
  645.  
  646.   /* Get a hold of the designated signal-receiving thread.  */
  647.   ss = _hurd_thread_sigstate (_hurd_sigthread);
  648.  
  649.   /* Post the signal; this will reply when the signal can be considered
  650.      delivered.  */
  651.   _hurd_internal_post_signal (ss, signo, 0, reply_port, reply_port_type);
  652.  
  653.   return MIG_NO_REPLY;        /* Already replied.  */
  654. }
  655.  
  656. extern void __mig_init (void *);
  657.  
  658. #include <mach/task_special_ports.h>
  659.  
  660. /* Initialize the message port and _hurd_sigthread and start the signal
  661.    thread.  */
  662.  
  663. void
  664. _hurdsig_init (void)
  665. {
  666.   error_t err;
  667.   vm_size_t stacksize;
  668.  
  669.   if (err = __mach_port_allocate (__mach_task_self (),
  670.                   MACH_PORT_RIGHT_RECEIVE,
  671.                   &_hurd_msgport))
  672.     __libc_fatal ("hurd: Can't create message port receive right\n");
  673.   
  674.   /* Make a send right to the signal port.  */
  675.   if (err = __mach_port_insert_right (__mach_task_self (),
  676.                       _hurd_msgport,
  677.                       _hurd_msgport,
  678.                       MACH_MSG_TYPE_MAKE_SEND))
  679.     __libc_fatal ("hurd: Can't create send right to message port\n");
  680.  
  681.   /* Set the default thread to receive task-global signals
  682.      to this one, the main (first) user thread.  */
  683.   _hurd_sigthread = __mach_thread_self ();
  684.  
  685.   /* Start the signal thread listening on the message port.  */
  686.  
  687.   if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
  688.     __libc_fatal ("hurd: Can't create signal thread\n");
  689.  
  690.   stacksize = __vm_page_size * 4; /* Small stack for signal thread.  */
  691.   if (err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
  692.                  _hurd_msgport_receive,
  693.                  (vm_address_t *) &__hurd_sigthread_stack_base,
  694.                  &stacksize))
  695.     __libc_fatal ("hurd: Can't setup signal thread\n");
  696.  
  697.   __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
  698.   __hurd_sigthread_variables =
  699.     malloc (__hurd_threadvar_max * sizeof (unsigned long int));
  700.   if (__hurd_sigthread_variables == NULL)
  701.     __libc_fatal ("hurd: Can't allocate thread variables for signal thread\n");
  702.  
  703.   /* Reinitialize the MiG support routines so they will use a per-thread
  704.      variable for the cached reply port.  */
  705.   __mig_init ((void *) __hurd_sigthread_stack_base);
  706.  
  707.   if (err = __thread_resume (_hurd_msgport_thread))
  708.     __libc_fatal ("hurd: Can't resume signal thread\n");
  709.     
  710. #if 0                /* Don't confuse poor gdb.  */
  711.   /* Receive exceptions on the signal port.  */
  712.   __task_set_special_port (__mach_task_self (),
  713.                TASK_EXCEPTION_PORT, _hurd_msgport);
  714. #endif
  715. }
  716.  
  717. /* Send exceptions for the signal thread to the proc server.
  718.    It will forward the message on to our message port,
  719.    and then restore the thread's state to code which
  720.    does `longjmp (_hurd_sigthread_fault_env, 1)'.  */
  721.  
  722. void
  723. _hurdsig_fault_init (void)
  724. {
  725.   error_t err;
  726.   mach_port_t sigexc;
  727.   struct machine_thread_state state;
  728.  
  729.   if (err = __mach_port_allocate (__mach_task_self (),
  730.                   MACH_PORT_RIGHT_RECEIVE, &sigexc))
  731.     __libc_fatal ("hurd: Can't create receive right for signal thread exc\n");
  732.  
  733.   /* Set up STATE with a thread state that will longjmp immediately.  */
  734.   _hurd_initialize_fault_recovery_state (&state);
  735.  
  736. #if 0                /* Don't confuse gdb.  */
  737.   __thread_set_special_port (_hurd_msgport_thread,
  738.                  THREAD_EXCEPTION_PORT, sigexc);
  739. #endif
  740.  
  741.   if (err = __USEPORT
  742.       (PROC,
  743.        __proc_handle_exceptions (port,
  744.                  sigexc,
  745.                  _hurd_msgport, MACH_MSG_TYPE_COPY_SEND,
  746.                  MACHINE_THREAD_STATE_FLAVOR,
  747.                  (int *) &state, MACHINE_THREAD_STATE_COUNT)))
  748.     __libc_fatal ("hurd: proc won't handle signal thread exceptions\n");
  749. }
  750.                 /* XXXX */
  751. static void
  752. reauth_proc (mach_port_t new)
  753. {
  754.   mach_port_t ignore;
  755.  
  756.   /* Reauthenticate with the proc server.  */
  757.   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
  758.                __proc_reauthenticate (port, _hurd_pid) ||
  759.                __auth_user_authenticate (new, port, _hurd_pid,
  760.                          &ignore))
  761.       && ignore != MACH_PORT_NULL)
  762.     __mach_port_deallocate (__mach_task_self (), ignore);
  763. }
  764. text_set_element (__hurd_reauth_hook, reauth_proc);
  765.